package programs.expression.superClasses;
import game.Ship;

import java.util.*;

import programs.expression.implementedClasses.Variable;

public abstract class ComposedExpression extends Expression {

	private final List<Expression> subExpressions = new ArrayList<Expression>();
	
	public ComposedExpression(Expression...subExpressions) {
		for(int i = 1; i <= subExpressions.length; i++) {
			Expression sub = subExpressions[i-1];
			this.subExpressions.add(i-1,sub);
		}
	}
	public List<Expression> getSubExpressions(){
		return this.subExpressions;
	}
	
	@Override
	public Set<Variable> getVariables(){
		Set<Variable> set = new HashSet<Variable>();
		for(Expression expr : getSubExpressions()){
			set.addAll(expr.getVariables());
		}
		return set;
	}
	@Override
	public abstract Object getValue();

	@Override
	public abstract ExpressionType getReturnType();

	@Override
	public boolean isValidExpression() {
		for(Expression subExpression : subExpressions) {
			if(! subExpression.isValidExpression())
				return false;
		}
		return true;
	}
	
	public int getNbOfSubExpressions()  {
		return subExpressions.size();
	}
	
	public Expression getSubExpressionAt(int index) throws IndexOutOfBoundsException {
		if(index < 1 || index > getNbOfSubExpressions())
			throw new IndexOutOfBoundsException();
		else 
			return subExpressions.get(index - 1);
	}
	
	private void setSubExpressionAt(int index, Expression subExpression)
			throws IndexOutOfBoundsException {
		if(index < 1 || index > getNbOfSubExpressions())
			throw new IndexOutOfBoundsException();
		else {
			subExpressions.set(index-1, subExpression);
		}
	}
	
	public boolean isValidSubExpressionAt(int index, Expression subExpression) {
		return getSubExpressionAt(index).getReturnType() == subExpression.getReturnType();
	}
	
	@Override 
	public Expression assignGlobalVariable(Variable variable) {
		for(int i = 1; i <= getNbOfSubExpressions(); i++) {
			Expression sub = getSubExpressionAt(i);
			setSubExpressionAt(i, sub.assignGlobalVariable(variable));
		}
		return this;
	}
	
	@Override
	public void setExecuter(Ship executer) {
		super.setExecuter(executer);
		for(Expression sub : subExpressions)
			sub.setExecuter(executer);
	}
}
